﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
using DailyBurnSharp.Exceptions;
using DailyBurnSharp.Model;

namespace DailyBurnSharp
{
    public class DailyBurnService
    {
        private const string API_URL = "https://dailyburn.com/api";
        private const string API_KEY = "gxMYxfqX1FaUTBCRvoEaA";

        public string Username { get; set; }
        public string Password { get; set; }

        public DailyBurnService() {}

        public DailyBurnService(string pUsername, string pPassword)
        {
            this.Username = pUsername;
            this.Password = pPassword;
        }

        #region Methods

        #region Public

        public virtual User GetUserProfile()
        {
            string methodUrl = "/users/current.xml";

            return XmlParser.ParseUser(CallApi(methodUrl));
        }

        public List<WeightEntry> GetUserWeightEntries()
        {
            string methodUrl = "/body_log_entries.xml";

            return XmlParser.ParseWeightEntries(CallApi(methodUrl));
        }

        public List<Food> GetUserFavoriteFoods()
        {
            string methodUrl = "/foods/favorites.xml";

            return XmlParser.ParseFoods(CallApi(methodUrl));
        }

        public List<Food> SearchFoods(string query)
        {
            string methodUrl = "/foods/search.xml";

            var parameters = new Dictionary<string, string>();
            parameters.Add("input", query);

            return XmlParser.ParseFoods(CallApi(methodUrl, parameters));
        }

        #endregion // Public

        #region Private

        private XmlDocument CallApi(string methodUrl)
        {
            return CallApi(methodUrl, new Dictionary<string, string>());
        }

        private XmlDocument CallApi(string methodUrl, Dictionary<string, string> parameters)
        {
            string url = API_URL + methodUrl;
            parameters.Add("key", API_KEY);

            url = ParamaterizeUrl(url, parameters);

            // Create the web request
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);

            // Add credentials to request  
            byte[] authBytes = Encoding.UTF8.GetBytes(String.Format("{0}:{1}", this.Username, this.Password).ToCharArray());
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(authBytes);

            try
            {
                using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    XmlDocument doc = new XmlDocument();
                    doc.Load(reader);

                    return doc;
                }
            }
            catch (WebException webException)
            {
                if (webException.Message.Contains("401"))
                    throw new DailyBurnAuthenticationException("Authentication failed, please check your username/password.");
                else
                    throw;
            }
        }

        private string ParamaterizeUrl(string url, Dictionary<string, string> parameters)
        {
            string paramaterizedUrl = url;

            if (parameters.Count > 0)
                paramaterizedUrl += "?";
            else
                return url;

            // append parameters
            foreach (string key in parameters.Keys)
            {
                paramaterizedUrl += key + "=" + HttpUtility.UrlEncode(parameters[key]) + "&";
            }

            // remove trailing "&"
            return paramaterizedUrl.Substring(0, paramaterizedUrl.Length - 1);
        }

        #endregion // Private

        #endregion // Methods
    }
}